/**
 * Step-0
 * 创建一个div标签添加到页面
 * 创建div
 * 创建textNode
 * 添加到根结点
 */
(() => {
  const divEl = document.createElement("div");
  divEl.id = "app";
  const textEl = document.createTextNode("Hello, mini-react! stop-0");
  divEl.append(textEl);
  document.querySelector("#root").appendChild(divEl);
})();

/**
 * Step-1
 * 1. div标签抽象成一个对象，把这个对象叫做vdom
 *    vdom对象由2个属性构成： type props
 *    type: "div"
 *    props :{ id: "ap", children: [], class style ... }
 *
 * 2. div还有一个文字节点，也抽象出vdom,由2个属性构成： type props
 *    type: "TEXT_ELEMENT"
 *    props: {nodeValue: "Hello, mini-react!", children: []}
 */

(() => {
  const divVdom = {
    type: "div",
    props: {
      id: "app",
      children: [],
    },
  };

  const textVdom = {
    type: "TEXT_ELEMENT",
    props: {
      nodeValue: "Hello, mini-react! step-1",
      children: [],
    },
  };
  // 使用vdom创建出div标签和文字节点
  const divEl = document.createElement(divVdom.type);
  const textEl = document.createTextNode(textVdom.props.nodeValue);
  divEl.appendChild(textEl);
  // 讲div元素添加到根结点
  document.querySelector("#root").append(divEl);
})();

/**
 * Step-2
 * 创建2个工厂函数分别用来创建：标签节点vdom，文字节点vdom
 * createElement createTextNode
 */

function createElement(type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      // children中有string 则创建 文字节点Vdom
      children: children.map((child) =>
        typeof child === "string" ? createTextNode(child) : child
      ),
    },
  };
}

function createTextNode(text) {
  return {
    type: "TEXT_ELEMENT",
    props: {
      nodeValue: text,
      children: [],
    },
  };
}

(() => {
  // 使用2个工厂函数创建vdom
  const textVdom = createTextNode("Hello, mini-react! step-2");
  const divVdom = createElement("div", { id: "app" }, textVdom);

  // 使用vdom创建div元素并挂载到根节点
  const textEl = document.createTextNode(textVdom.props.nodeValue);
  const divEl = document.createElement(divVdom.type);
  divEl.id = divVdom.props.id;
  divEl.appendChild(textEl);
  document.querySelector("#root").append(divEl);
})();

/**
 * Step-3
 * 创建render函数，用于根据vdom创建元素
 */

function render(vdom, container) {
  // // 1. 创建标签
  // if (vdom.type === "TEXT_ELEMENT") {
  //   const element = document.createElement(vdom.type);
  //   Object.keys(vdom.props).forEach((property) => {
  //     // 1.1 创建并挂载子节点
  //     if (property === "children") {
  //       vdom.props.children.forEach((vd) => {
  //         render(vd, element);
  //       });
  //     } else {
  //       // 1.2 添加属性
  //       element[property] = vdom.props[property];
  //     }
  //   });

  //   container.appendChild(element);
  // } else {
  //   // 2. 创建文字节点
  //   const textNode = document.createTextNode(vdom.props.nodeValue);
  //   container.appendChild(textNode);
  // }

  const dom =
    vdom.type === "TEXT_ELEMENT"
      ? document.createTextNode(vdom.props.nodeValue)
      : document.createElement(vdom.type);
  // 添加属性
  const props = vdom.props;
  Object.keys(props).forEach((prop) => {
    if (prop !== "children") {
      dom[prop] = props[prop];
    } else {
      props[prop].forEach((vd) => render(vd, dom));
    }
  });
  // debugger;
  container.appendChild(dom);
}

(() => {
  const textVdom = createTextNode("Hello, ");
  const divVdom = createElement(
    "div",
    { id: "app" },
    textVdom,
    "mini-react! ",
    "step-3"
  );
  render(divVdom, document.querySelector("#root"));
})();

const React = {
  render,
  createElement,
};

const ReactDom = {
  createRoot(root) {
    return {
      render(app) {
        render(app, root);
      },
    };
  },
};

const app = React.createElement(
  "div",
  { id: "app" },
  "Hello! mini-react finally"
);
ReactDom.createRoot(document.querySelector("#root")).render(app);
